package com.pan.concurrency.thread;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 *  线程的等待与唤醒：
 *      1. wait与notify都是必须获取到锁才能使用 如果没有获取锁就直接使用 会出现错误：
 *
 *      Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
 * 	        at java.lang.Object.wait(Native Method)
 * 	        at java.lang.Object.wait(Object.java:502)
 * 	        at com.pan.concurrency.thread.Consumer.run(WaitAndNotifyThread.java:87)
 *      java.lang.IllegalMonitorStateException
 * 	        at java.lang.Object.notify(Native Method)
 * 	        at com.pan.concurrency.thread.Producer.run(WaitAndNotifyThread.java:58)
 *
 * 	   2. 所以要加上synchronized
 *
 *
 *  应用场景:
 *      生产者与消费者
 *
 * </p>
 *
 * @author kaiji
 * @since 2020/1/25 15:38
 */
public class WaitAndNotifyThread {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        Producer producer = new Producer(list, "开机");
        Consumer consumer = new Consumer(list);

        producer.start();
        consumer.start();
    }
}

/**
 * 生产者
 */
class Producer extends Thread {
    // list 最大值
    private static final int MAX = 10;

    private List<Integer> list;
    private String username;

    public Producer(List<Integer> list, String username) {
        this.list = list;
        this.username = username;
    }

    @Override
    public void run() {

        int i = 1;
        try {
            synchronized (list) {
                do {
                    if (list.size() >= MAX) {
                        list.wait();
                    } else {
                        list.add(i);
                        System.out.println("producer : " + username + " 当前生产号为： " + i);
                        i++;
                        list.notify();
                    }
                } while (true);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


    }


}

/**
 * 消费者
 */
class Consumer extends Thread {

    private List<Integer> list;

    public Consumer(List<Integer> list) {
        this.list = list;
    }

    @Override
    public void run() {
        try {
            synchronized (list) {
                do {
                    if (list.isEmpty()) {
                        list.wait();
                    } else {
                        Integer consumerNo = list.remove(0);
                        System.out.println("当前消费者编号： " + consumerNo);
                        list.notify();
                    }
                } while (true);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
